package com.moodair.pip.core;

import cn.hutool.core.collection.CollUtil;
import com.moodair.pip.core.PipelineProperties.PipelineServerProperties;
import com.moodair.pip.core.annotation.PluginComponent;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 管道执行器
 *
 * @author MoodAir
 */
@Component
public class PipelineExecutor implements ApplicationContextAware {
    
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    Map<String, Object> plugin;
    
    private ApplicationContext appContext;
    
    @Autowired
    @Qualifier("pipelineProperties")
    private PipelineProperties properties;
    
    
    /**
     * 同步处理输入的上下文数据<br/> 如果处理时上下文数据流通到最后一个处理器且最后一个处理器返回 true，则返回 true，否则返回 false
     *
     * @param context 输入的上下文数据
     * @return 处理过程中管道是否畅通，畅通返回 true，不畅通返回 false
     */
    public boolean acceptSync(PipelineContext context,String name) {
        List<ContextHandler<? super PipelineContext>> handlers = new ArrayList<>();
        Objects.requireNonNull(context, "上下文数据不能为 null");
        // 获取数据处理管道
        Map<String, PipelineServerProperties> server = properties.getServer();
        PipelineServerProperties pipelineServerProperties = server.get(name);
        List<String> plugin = pipelineServerProperties.getPlugin();
        if (CollUtil.isEmpty(plugin)) {
            logger.error("{} 的管道为空", context);
        }
        for (String pipelineName : plugin) {
            Object o = this.plugin.get("pipeline.plugin." + pipelineName);
            if (Objects.isNull(o)) {
                logger.error("{} 的插件为空", pipelineName);
            }
            handlers.add((ContextHandler<? super PipelineContext>) o);
        }
        // 管道是否畅通
        boolean lastSuccess = true;
        for (ContextHandler<? super PipelineContext> handler : handlers) {
            try {
                // 当前处理器处理数据，并返回是否继续向下处理
                lastSuccess = handler.handle(context);
            } catch (Throwable ex) {
                lastSuccess = false;
                logger.error("[{}] 处理异常，handler={}", context.getName(), handler.getClass().getSimpleName(), ex);
            }
            // 不再向下处理
            if (!lastSuccess) {
                break;
            }
        }
        return lastSuccess;
    }
    
    @PostConstruct
    public void afterPropertiesSet() {
        plugin = appContext.getBeansWithAnnotation(PluginComponent.class);
    }
    
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        appContext = applicationContext;
    }
}